package com.aplana.ccsd.service;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Service;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;

import com.aplana.ccsd.model.pagination.PagedList;
import com.aplana.ccsd.model.pagination.Pagination;
import com.aplana.ccsd.model.pagination.Step;

@Service
public class PaginationServiceImpl implements PaginationService {

	protected static Integer MAX_RESULTS_PER_PAGE = 100;
	protected static Integer DEFAULT_RESULTS_PER_PAGE = 3;

	@Override
	public Step getCurrentStep(HttpServletRequest request)
			throws ServletRequestBindingException {
		Integer max = ServletRequestUtils.getIntParameter(request, "max");
		Integer offset = ServletRequestUtils.getIntParameter(request, "offset");
		if (max == null || offset == null) {
			return new Step(DEFAULT_RESULTS_PER_PAGE, 0);
		}
		if (max.intValue() <= 0) {
			max = Integer.valueOf(1);
		}
		if (max.intValue() > MAX_RESULTS_PER_PAGE) {
			max = Integer.valueOf(MAX_RESULTS_PER_PAGE);
		}

		Step step = new Step(max, offset);
		return step;
	}

	@Override
	public <T> PagedList<T> createPageResults(List<T> allResult,
			Step currentStep) {
		int total = allResult.size();
		int newMax = currentStep.getMax();
		int offset = currentStep.getOffset();
		List<T> result;
		if (total > offset) {
			if (total < offset + currentStep.getMax()) {
				newMax = total - offset;
			}

			result = allResult.subList(offset, offset + newMax);
		} else {
			result = new ArrayList<T>();
		}

		return new PagedList<T>(total, result);
	}

	@Override
	public Pagination createPagination(String url,
			HttpServletRequest request, Step currentStep, int total) {
		int nbPages = (int) Math.ceil((double) total / currentStep.getMax());
		if (nbPages < 2) {
			return null;
		}
		int indexPage = (int) Math.ceil((double) currentStep.getOffset()
				/ currentStep.getMax());
		currentStep.setIndex(indexPage + 1);

		Pagination pagination = new Pagination();
		pagination.setCurrentLink(currentStep);
		if (indexPage > 0 && nbPages > 1) {
			pagination.setPrevLink(new Step(currentStep.getMax(), currentStep
					.getOffset() - currentStep.getMax(), 1));
		}
		if (indexPage < (nbPages - 1) && nbPages > 1) {
			pagination.setNextLink(new Step(currentStep.getMax(), currentStep
					.getOffset() + currentStep.getMax(), nbPages));
		}
		List<Step> stepLinks = new ArrayList<Step>();
		for (int i = 0; i < nbPages; i++) {
			stepLinks.add(new Step(currentStep.getMax(), i
					* currentStep.getMax(), i + 1));
		}
		pagination.setStepLinks(stepLinks);
		pagination.setPath(url);

		return pagination;
	}

}